import org.json.*;

public class GameState implements JSONString {  
  private Map gameMap;
  private Player me;
  private Clock clock;
  
  private boolean godMode = false;
  
  private GameState(Map gameMap, Player me, Clock clock, boolean godMode) {
    this.gameMap = gameMap;
    this.me = me;
    this.clock = clock;
    this.godMode = godMode;
  }
  
  public static GameState createDefault() {
    return createDefaultWithPlayer(null);
  }
  
  public static GameState createDefaultWithPlayer(Player me) {
    return new GameState(Map.empty(30,20),me,Clock.create(0),false);
  }
  
  public static GameState fromJSON(JSONObject json) {
    try {
      if(json.getString("className").equals("GameState")) {
        return new GameState(Map.fromJSON(json.getJSONObject("gameMap")),
                             Player.fromJSON(json.getJSONObject("me")),
                             Clock.fromJSON(json.getJSONObject("clock")),
                             json.getBoolean("godMode"));
      } else {
        System.err.println("\"" + json.toString() + "\" does not represent a GameState.");
        throw new RuntimeException("Cannot parse JSON, it is not a GameState!");
      }
    } catch (JSONException e) {
      e.printStackTrace();
      throw new RuntimeException("Unrecoverable JSON error, see above stack trace");
    }
    
  }

  @Override
  public String toJSONString() {
    try {
      return new JSONStringer()
                        .object() 
                          .key("className")
                          .value("GameState")
                          .key("gameMap")
                          .value(this.map())
                          .key("me")
                          .value(this.me())
                          .key("clock")
                          .value(this.clock())
                          .key("godMode")
                          .value(this.godMode)
                        .endObject().toString();
    } catch (JSONException e) {
      e.printStackTrace();
      throw new RuntimeException("Unrecoverable JSON error, see above stack trace.");
    }
  }
  
  public Clock clock() {
    return clock;
  }
  
  public boolean isGodMode() {
    return godMode;
  }
  
  public void toggleGodMode() {
    if (godMode)
      godMode = false;
    else
      godMode = true;
  }
  
  public Map map() {
    return gameMap;
  }
  
  public void updateMap(Map m) {
    if (!m.size().equals(gameMap.size()))
      throw new IllegalArgumentException("SpaceGame.updateMap()");
    gameMap = m;
  }
  
  public Player me() {
    return me;
  }
  
  public void setMe(Player me) {
    this.me = me;
  }
  
}
